package com.example.mcp.service;

import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * MCP客户端服务 - 封装McpSyncClient功能
 * 提供从服务端获取消息的能力
 */
@Service
public class McpClientService {

    private static final Logger logger = LoggerFactory.getLogger(McpClientService.class);

    @Value("${mcp.client.server-url:http://localhost:8081}")
    private String serverUrl;

    @Value("${mcp.client.sse-endpoint:/sse}")
    private String sseEndpoint;

    @Value("${mcp.client.request-timeout:10}")
    private int requestTimeout;

    @Value("${mcp.client.initialization-timeout:5}")
    private int initializationTimeout;

    @Value("${mcp.client.prevent-duplicate-calls:true}")
    private boolean preventDuplicateCalls;

    @Value("${mcp.client.duplicate-check-window:5000}")
    private long duplicateCheckWindow;

    private McpSyncClient client;
    private McpClientTransport transport;
    private volatile boolean isHealthy = false;

    public McpClientService() {
        initialize();
    }

    @PostConstruct
    public void initialize() {
        logger.info("🔄 初始化MCP客户端 initialize() 方法被调用");
        CompletableFuture.runAsync(() -> {
            try {
                initializeClient();
            } catch (Exception e) {
                logger.error("❌ 延迟初始化失败", e);
            }
        });
    }

    private void initializeClient() {
        if (client != null) {
            logger.info("ℹ️ MCP客户端已初始化，跳过重复初始化");
            return;
        }

        try {
            logger.info("🚀 初始化MCP客户端服务");
            logger.info("📡 服务器地址: {}{}", serverUrl, sseEndpoint);

            // 先检查服务器是否可访问
            if (!isServerReachable()) {
                logger.warn("⚠️ MCP服务器不可访问，延迟初始化");
                return;
            }

            // 创建HTTP SSE传输层
            transport = HttpClientSseClientTransport.builder(serverUrl)
                    .sseEndpoint(sseEndpoint)
                    .build();

            // 创建同步MCP客户端
            client = McpClient.sync(transport)
                    .requestTimeout(Duration.ofSeconds(requestTimeout))
                    .initializationTimeout(Duration.ofSeconds(initializationTimeout))
                    .capabilities(McpSchema.ClientCapabilities.builder().roots(true).sampling().build())
                    .clientInfo(new McpSchema.Implementation("mcp-client-service", "1.0.0"))
                    .loggingConsumer(notification -> {
                        logger.info("📝 [MCP日志] [{}] {}: {}",
                                notification.level(), notification.logger(), notification.data());
                    })
                    .progressConsumer(notification -> {
                        logger.info("📊 [进度更新] {}: {}/{} - {}",
                                notification.progressToken(), notification.progress(),
                                notification.total(), notification.message());
                    })
                    .build();

            // 初始化客户端
//            client.initialize();
//            isHealthy = true;
            logger.info("✅ MCP客户端服务初始化成功");

            return; // 成功初始化，退出重试循环

        } catch (Exception e) {
            logger.error("❌ MCP客户端服务初始化失败 ", e.getMessage());
        }
    }

    /**
     * 检查MCP服务器是否可访问
     */
    private boolean isServerReachable() {
        try {
            java.net.URL url = new java.net.URL(serverUrl + sseEndpoint);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000); // 5秒连接超时
            connection.setReadTimeout(5000);    // 5秒读取超时
            connection.connect();
            int responseCode = connection.getResponseCode();
            connection.disconnect();

            logger.info("🔍 MCP服务器连接检查: {} (响应码: {})", serverUrl + sseEndpoint, responseCode);
            return responseCode == 200 || responseCode == 404; // 404也算可访问，说明服务器在运行

        } catch (Exception e) {
            logger.warn("⚠️ MCP服务器连接检查失败: {}", e.getMessage());
            return false;
        }
    }

    @PreDestroy
    public void shutdown() {
        try {
            if (client != null) {
                client.close();
                logger.info("🔒 MCP客户端已关闭");
            }
        } catch (Exception e) {
            logger.error("❌ 关闭MCP客户端时出错", e);
        }
    }

    /**
     * 获取所有聊天记录
     */
    public CompletableFuture<String> getAllConversations() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("📋 获取所有聊天记录");

                // 检查客户端是否已初始化
                // 检查客户端是否已初始化
                if (client == null) {
                    logger.warn("⚠️ MCP客户端未初始化，尝试重新初始化");
                    return "⚠️ MCP客户端未初始化，尝试重新初始化";
                }

                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("get_all_conversations", Map.of());
                McpSchema.CallToolResult result;

                try {
                    result = client.callTool(request);
                } catch (Exception e) {
                    logger.error("❌ MCP服务器调用异常: {}", e.getMessage());
                    return "错误：MCP服务器调用失败 - " + e.getMessage();
                }

                if (result.isError()) {
                    logger.error("❌ 获取聊天记录失败: {}", result.content());
                    return "错误: " + result.content();
                }

                logger.info("✅ 获取聊天记录成功");
                return result.content().toString();

            } catch (Exception e) {
                logger.error("❌ 获取聊天记录异常", e);
                return "异常: " + e.getMessage();
            }
        });
    }

    /**
     * 根据ID获取聊天记录
     */
    public CompletableFuture<String> getConversationById(String conversationId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("🔍 获取聊天记录详情: {}", conversationId);
                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("get_conversation_by_id",
                        Map.of("conversation_id", conversationId));
                McpSchema.CallToolResult result = client.callTool(request);

                if (result.isError()) {
                    logger.error("❌ 获取聊天记录详情失败: {}", result.content());
                    return "错误: " + result.content();
                }

                logger.info("✅ 获取聊天记录详情成功");
                return result.content().toString();

            } catch (Exception e) {
                logger.error("❌ 获取聊天记录详情异常", e);
                return "异常: " + e.getMessage();
            }
        });
    }

    /**
     * 根据会话ID获取消息列表
     */
    public CompletableFuture<String> getMessagesByConversationId(String conversationId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("📋 获取会话消息列表: {}", conversationId);

                // 检查客户端是否已初始化
                if (client == null) {
                    logger.warn("⚠️ MCP客户端未初始化，尝试重新初始化");
                    return "⚠️ MCP客户端未初始化，尝试重新初始化";
                }

                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("get_messages_by_conversation_id",
                        Map.of("conversation_id", conversationId));

                McpSchema.CallToolResult result;
                try {
                    result = client.callTool(request);
                } catch (Exception e) {
                    logger.error("❌ MCP服务器调用异常: {}", e.getMessage());
                    return "错误：MCP服务器调用失败 - " + e.getMessage();
                }

                if (result.isError()) {
                    logger.error("❌ 获取消息列表失败: {}", result.content());
                    return "错误: " + result.content();
                }

                logger.info("✅ 获取消息列表成功");
                return result.content().toString();

            } catch (Exception e) {
                logger.error("❌ 获取消息列表异常", e);
                return "异常: " + e.getMessage();
            }
        });
    }

    /**
     * 发送消息
     */
    public CompletableFuture<String> sendMessage(String conversationId, String sender, String content) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("📤 发送消息到会话: {}", conversationId);
                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("send_message",
                        Map.of(
                                "conversation_id", conversationId,
                                "sender", sender,
                                "content", content
                        ));
                McpSchema.CallToolResult result = client.callTool(request);

                if (result.isError()) {
                    logger.error("❌ 发送消息失败: {}", result.content());
                    return "错误: " + result.content();
                }

                logger.info("✅ 发送消息成功");
                return result.content().toString();

            } catch (Exception e) {
                logger.error("❌ 发送消息异常", e);
                return "异常: " + e.getMessage();
            }
        });
    }

    /**
     * Ping测试连接
     */
    public CompletableFuture<String> ping() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("🏓 执行Ping测试");

                // 检查客户端是否已初始化
                if (client == null) {
                    logger.warn("⚠️ MCP客户端未初始化，尝试重新初始化");
                    return "⚠️ MCP客户端未初始化，尝试重新初始化";
                }

                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("ping", Map.of());

                McpSchema.CallToolResult result;
                try {
                    result = client.callTool(request);
                } catch (Exception e) {
                    logger.error("❌ MCP服务器调用异常: {}", e.getMessage());
                    return "错误：MCP服务器调用失败 - " + e.getMessage();
                }

                if (result.isError()) {
                    logger.error("❌ Ping测试失败: {}", result.content());
                    return "错误: " + result.content();
                }

                logger.info("✅ Ping测试成功");
                return result.content().toString();

            } catch (Exception e) {
                logger.error("❌ Ping测试异常", e);
                return "异常: " + e.getMessage();
            }
        });
    }

    /**
     * 检查客户端是否已初始化
     */
    public boolean isInitialized() {
        return client != null;
    }

    /**
     * 检查MCP服务器连接状态
     */
    public CompletableFuture<String> checkServerConnection() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                logger.info("🔍 检查MCP服务器连接状态: {}{}", serverUrl, sseEndpoint);

                // 检查客户端是否已初始化
                if (client == null) {
                    return "MCP客户端未初始化，请检查服务器连接";
                }

                // 尝试ping服务器
                McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("ping", Map.of());
                McpSchema.CallToolResult result = client.callTool(request);

                if (result.isError()) {
                    return "MCP服务器响应错误: " + result.content();
                }

                return "MCP服务器连接正常: " + result.content();

            } catch (Exception e) {
                logger.error("❌ 检查MCP服务器连接失败", e);
                return "MCP服务器连接失败: " + e.getMessage();
            }
        });
    }

    /**
     * 强制重新初始化MCP客户端（公共方法）
     */
    public synchronized void forceReinitialize() {
        logger.info("🔄 强制重新初始化MCP客户端");
        reinitialize();
    }

    /**
     * 检查连接健康状态
     */
    public boolean isConnectionHealthy() {
        try {
            if (client == null) {
                isHealthy = false;
                return false;
            }

            // 尝试ping服务器，设置较短的超时时间
            McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("ping", Map.of());
            McpSchema.CallToolResult result = client.callTool(request);

            isHealthy = !result.isError();
            return isHealthy;

        } catch (Exception e) {
            logger.warn("⚠️ 连接健康检查失败: {}", e.getMessage());
            isHealthy = false;
            return false;
        }
    }

    /**
     * 获取连接健康状态
     */
    public boolean getHealthStatus() {
        return isHealthy;
    }

    /**
     * 重新初始化MCP客户端
     */
    private synchronized void reinitialize() {
        logger.info("🔄 重新初始化MCP客户端");
        initialize();

    }
}
